/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zlang_in.h"

int InitObjectStack( struct ZlangRuntime *rt , struct ZlangObjectsStack *objs_stack , int default_size , int increase_size )
{
	objs_stack->objs_stack_size = default_size ;
	objs_stack->objs_stack = (struct ZlangObject *)ZLMALLOC( sizeof(struct ZlangObject) * objs_stack->objs_stack_size ) ;
	if( objs_stack->objs_stack == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for %s_objs_stack" , (objs_stack==&(rt->local_objs_stack)?"local":"tmp") )
		return ZLANG_ERROR_ALLOC;
	}
	memset( objs_stack->objs_stack , 0x00 , sizeof(struct ZlangObject) * objs_stack->objs_stack_size );
	objs_stack->increase_size = increase_size ;
	
	return 0;
}

void CleanObjectsStack( struct ZlangRuntime *rt , struct ZlangObjectsStack *objs_stack )
{
	ZLFREE( objs_stack->objs_stack );
	
	return;
}

static int TryIncreaseObjectsStack( struct ZlangRuntime *rt , struct ZlangObjectsStack *objs_stack , struct ZlangObjectsStackInfo *objs_stack_info )
{
	if( objs_stack_info->stack_local_var_top >= objs_stack->objs_stack_size )
	{
		int			new_objs_stack_size ;
		struct ZlangObject	*new_objs_stack = NULL ;
		
		new_objs_stack_size = objs_stack->objs_stack_size + objs_stack->increase_size ;
		new_objs_stack = (struct ZlangObject *)ZLREALLOC( objs_stack->objs_stack , sizeof(struct ZlangObject) * new_objs_stack_size ) ;
		if( new_objs_stack == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "ZLREALLOC memory for %s_objs_stack" , (objs_stack==&(rt->tmp_objs_stack)?"tmp":"local") )
			return ZLANG_ERROR_ALLOC;
		}
		objs_stack->objs_stack = new_objs_stack ;
		objs_stack->objs_stack_size = new_objs_stack_size ;
	}
	
	return 0;
}

struct ZlangObject *PushLocalObjectsStack( struct ZlangRuntime *rt , struct ZlangObjectsStack *objs_stack , struct ZlangObjectsStackInfo *objs_stack_info )
{
	struct ZlangObject		*obj = NULL ;
	int				nret = 0 ;
	
	nret = TryIncreaseObjectsStack( rt , objs_stack , objs_stack_info ) ;
	if( nret )
		return NULL;
	
	obj = objs_stack->objs_stack + objs_stack_info->stack_local_var_top ;
	memset( obj , 0x00 , sizeof(struct ZlangObject) );
	objs_stack_info->stack_local_var_top++;
	
	return obj;
}

int PopupObjectsStack( struct ZlangRuntime *rt , struct ZlangObjectsStack *objs_stack , struct ZlangObjectsStackInfo *objs_stack_info )
{
	int				stack_no ;
	struct ZlangObject		*obj = NULL ;
	
	if( objs_stack_info->stack_local_var_top <= 0 )
		return ZLANG_ERROR_PARAMETER;
	
	stack_no = objs_stack_info->stack_local_var_top-1 ;
	obj = objs_stack->objs_stack + stack_no ;
	TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "    popup " ); DebugPrintObject(rt,obj); printf( " from %s_stack_no[%d]" , (objs_stack==&(rt->local_objs_stack)?"local":"tmp") , stack_no ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	
	CleanObject( rt , obj );
	
	objs_stack_info->stack_local_var_top--;
	
	return 0;
}

int GetStackTop( struct ZlangRuntime *rt , struct ZlangObjectsStackInfo *objs_stack_info )
{
	return objs_stack_info->stack_local_var_top;
}

struct ZlangObject *GetStackTopObject( struct ZlangRuntime *rt , struct ZlangObjectsStack *objs_stack )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	
	return objs_stack->objs_stack + local_objs_stack_info->stack_local_var_top-1;
}

struct ZlangObject *GetStackObject( struct ZlangRuntime *rt , struct ZlangObjectsStack *objs_stack , int stack_no )
{
	return objs_stack->objs_stack+stack_no;
}

struct ZlangObject *CloneObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name , struct ZlangObject *clone_obj )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	struct ZlangObject		*obj = NULL ;
	int				nret = 0 ;
	
	obj = PushLocalObjectsStack( rt , & (rt->local_objs_stack) , local_objs_stack_info ) ;
	if( obj == NULL )
		return NULL;
	
	nret = CloneObject( rt , & obj , obj_name , clone_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneZObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetZObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneStringObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetStringObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneBoolObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetBoolObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneShortObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetShortObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneUShortObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetUShortObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneIntObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetIntObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneUIntObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetUIntObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneLongObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetLongObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneULongObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetULongObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneFloatObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetFloatObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneDoubleObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetDoubleObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneArrayObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetArrayObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneListObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetListObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneListNodeObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetListNodeObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneMapObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetMapObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneIteratorObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetIteratorObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneFunctionPtrObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInLocalStack( rt , obj_name , GetFunctionPtrObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *PushInputObjectsStack( struct ZlangRuntime *rt , struct ZlangObjectsStack *objs_stack , struct ZlangObjectsStackInfo *objs_stack_info )
{
	struct ZlangObject		*obj = NULL ;
	int				nret = 0 ;
	
	nret = TryIncreaseObjectsStack( rt , objs_stack , objs_stack_info ) ;
	if( nret )
		return NULL;
	
	obj = objs_stack->objs_stack + objs_stack_info->stack_in_params_top ;
	objs_stack_info->stack_in_params_top++;
	
	return obj;
}

struct ZlangObject *ReferObjectInLocalStack( struct ZlangRuntime *rt , char *obj_name , struct ZlangObject *refer_obj )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	struct ZlangObject		*obj = NULL ;
	int				nret = 0 ;
	
	obj = PushLocalObjectsStack( rt , & (rt->local_objs_stack) , local_objs_stack_info ) ;
	if( obj == NULL )
		return NULL;
	
	nret = SetObjectName( rt , obj , obj_name ) ;
	if( nret )
		return NULL;
	
	nret = ReferObject( rt , obj , refer_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

int InitLocalObjecsStackInfoArray( struct ZlangRuntime *rt )
{
	rt->local_objs_stack_info_array_allocount = ZLANG_LOCAL_OBJECTS_STACK_INFO_ARRAY_COUNT_DEFAULT ;
	rt->local_objs_stack_info_array = (struct ZlangObjectsStackInfo *)ZLMALLOC( sizeof(struct ZlangObjectsStackInfo) * rt->local_objs_stack_info_array_allocount ) ;
	if( rt->local_objs_stack_info_array == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for local_objs_stack_info_array" )
		return ZLANG_ERROR_ALLOC;
	}
	memset( rt->local_objs_stack_info_array , 0x00 , sizeof(struct ZlangObjectsStackInfo) * rt->local_objs_stack_info_array_allocount );
	
	return 0;
}

void CleanLocalObjecsStackInfoArray( struct ZlangRuntime *rt )
{
	ZLFREE( rt->local_objs_stack_info_array );
	
	return;
}

static int TryIncreaseLocalObjecsStackInfoArray( struct ZlangRuntime *rt )
{
	if( rt->local_objs_stack_info_array_curridx >= rt->local_objs_stack_info_array_allocount-1 )
	{
		int				new_objs_stack_info_array_allocount ;
		struct ZlangObjectsStackInfo	*new_objs_stack_info_array = NULL ;
		
		new_objs_stack_info_array_allocount = rt->local_objs_stack_info_array_allocount + ZLANG_LOCAL_OBJECTS_STACK_INFO_ARRAY_INCREASE_COUNT ;
		new_objs_stack_info_array = (struct ZlangObjectsStackInfo *)ZLREALLOC( rt->local_objs_stack_info_array , sizeof(struct ZlangObjectsStackInfo) * new_objs_stack_info_array_allocount ) ;
		if( new_objs_stack_info_array == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "ZLREALLOC memory for local_objs_stack_info_array" )
			return ZLANG_ERROR_ALLOC;
		}
		rt->local_objs_stack_info_array = new_objs_stack_info_array ;
		rt->local_objs_stack_info_array_allocount = new_objs_stack_info_array_allocount ;
	}
	
	return 0;
}

struct ZlangObjectsStackInfo *IncreaseLocalObjectsStackInfo( struct ZlangRuntime *rt , char *full_func_name )
{
	struct ZlangObjectsStackInfo	*old_local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	int				stack_local_var_top ;
	struct ZlangObjectsStackInfo	*new_local_objs_stack_info = NULL ;
	
	stack_local_var_top = GetStackTop( rt , old_local_objs_stack_info );
	
	TryIncreaseLocalObjecsStackInfoArray( rt );
	
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangObjectsStackInfo *local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "before increase local stack : [%d][%s]-[%d][%d][%d][%d]" , rt->local_objs_stack_info_array_curridx,local_objs_stack_info->full_func_name , local_objs_stack_info->stack_bottom,local_objs_stack_info->stack_in_params_top,local_objs_stack_info->stack_out_params_top,local_objs_stack_info->stack_local_var_top )
	}
	
	rt->local_objs_stack_info_array_curridx++;
	new_local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	new_local_objs_stack_info->stack_local_var_top = stack_local_var_top ;
	new_local_objs_stack_info->stack_out_params_top = stack_local_var_top ;
	new_local_objs_stack_info->stack_in_params_top = stack_local_var_top ;
	new_local_objs_stack_info->stack_bottom = stack_local_var_top ;
	new_local_objs_stack_info->full_func_name = full_func_name ;
	
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangObjectsStackInfo *local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "after increase local stack : [%d][%s]-[%d][%d][%d][%d]" , rt->local_objs_stack_info_array_curridx,local_objs_stack_info->full_func_name , local_objs_stack_info->stack_bottom,local_objs_stack_info->stack_in_params_top,local_objs_stack_info->stack_out_params_top,local_objs_stack_info->stack_local_var_top )
	}
	
	return new_local_objs_stack_info;
}

struct ZlangObjectsStackInfo *DecreaseLocalObjectsStackInfo( struct ZlangRuntime *rt )
{
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangObjectsStackInfo *local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "before decrease local stack : [%d][%s]-[%d][%d][%d][%d]" , rt->local_objs_stack_info_array_curridx,local_objs_stack_info->full_func_name , local_objs_stack_info->stack_bottom,local_objs_stack_info->stack_in_params_top,local_objs_stack_info->stack_out_params_top,local_objs_stack_info->stack_local_var_top )
	}
	
	PopupLocalObjectsStack( rt );
	
	memset( rt->local_objs_stack_info_array+rt->local_objs_stack_info_array_curridx , 0x00 , sizeof(struct ZlangObjectsStackInfo) );
	rt->local_objs_stack_info_array_curridx--;
	
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangObjectsStackInfo *local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "after decrease local stack : [%d][%s]-[%d][%d][%d][%d]" , rt->local_objs_stack_info_array_curridx,local_objs_stack_info->full_func_name , local_objs_stack_info->stack_bottom,local_objs_stack_info->stack_in_params_top,local_objs_stack_info->stack_out_params_top,local_objs_stack_info->stack_local_var_top )
	}
	
	return GetCurrentLocalObjectsStackInfo( rt );
}

void SetObjectsStackFullFuncName( struct ZlangObjectsStackInfo *objs_stack_info , char *full_func_name )
{
	objs_stack_info->full_func_name = full_func_name ;
	
	return;
}

char *GetObjectsStackFullFuncName( struct ZlangObjectsStackInfo *objs_stack_info )
{
	return objs_stack_info->full_func_name;
}

struct ZlangObjectsStackInfo *GetCurrentLocalObjectsStackInfo( struct ZlangRuntime *rt )
{
	return rt->local_objs_stack_info_array+rt->local_objs_stack_info_array_curridx;
}

int GetCurrentLocalObjectsStackInfoIndex( struct ZlangRuntime *rt )
{
	return rt->local_objs_stack_info_array_curridx;
}

void MarkInputParamtersTop( struct ZlangObjectsStackInfo *local_objs_stack_info )
{
	local_objs_stack_info->stack_in_params_top = local_objs_stack_info->stack_local_var_top ;
	return;
}

void MarkOutputParamtersTop( struct ZlangObjectsStackInfo *local_objs_stack_info )
{
	local_objs_stack_info->stack_out_params_top = local_objs_stack_info->stack_local_var_top ;
	return;
}

struct ZlangObjectsStackInfo *GetPreviousObjectsStackInfo( struct ZlangRuntime *rt , struct ZlangObjectsStackInfo *local_objs_stack_info )
{
	if( local_objs_stack_info == rt->local_objs_stack_info_array )
		return NULL;
	
	return local_objs_stack_info-1;
}

struct ZlangObjectsStackInfo *GetFunctionLocalObjectsStackInfo( struct ZlangRuntime *rt )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	
	while( local_objs_stack_info->full_func_name == NULL )
	{
		local_objs_stack_info = GetPreviousObjectsStackInfo( rt , local_objs_stack_info ) ;
		if( local_objs_stack_info == NULL )
			return NULL;
	}
	
	return local_objs_stack_info;
}

struct ZlangObjectsStackInfo *GetFirstLocalObjectsStackInfo( struct ZlangRuntime *rt )
{
	return rt->local_objs_stack_info_array;
}

int PopupLocalObjectsStack( struct ZlangRuntime *rt )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	int				nret = 0 ;
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "  PopupObjectsStack local_objs_stack_info[%s]-[%d][%d][%d][%d]" , local_objs_stack_info->full_func_name , local_objs_stack_info->stack_bottom,local_objs_stack_info->stack_in_params_top,local_objs_stack_info->stack_out_params_top,local_objs_stack_info->stack_local_var_top )
	
	while( local_objs_stack_info->stack_local_var_top > local_objs_stack_info->stack_bottom )
	{
		nret = PopupObjectsStack( rt , & (rt->local_objs_stack) , local_objs_stack_info ) ;
		if( nret )
			return nret;
	}
	
	local_objs_stack_info->stack_local_var_top = local_objs_stack_info->stack_bottom ;
	local_objs_stack_info->stack_out_params_top = local_objs_stack_info->stack_bottom ;
	local_objs_stack_info->stack_in_params_top = local_objs_stack_info->stack_bottom ;
	
	return 0;
}

struct ZlangObject *QueryObjectInStatementSegment( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	struct ZlangObject		*obj = NULL ;
	int				stack_no ;
	
	TEST_RUNTIME_DEBUG( rt )
	{
		DebugStack( rt );
	}
	
	if( obj_name == NULL || obj_name[0] == '\0' )
		return NULL;
	
	for( stack_no = local_objs_stack_info->stack_local_var_top-1 ; stack_no >= local_objs_stack_info->stack_out_params_top ; stack_no-- )
	{
		obj = rt->local_objs_stack.objs_stack + stack_no ;
		if( obj->obj_name && obj->obj_name[0] && STRCMP( obj->obj_name , == , obj_name ) )
			return obj;
	}
	
	return NULL;
}

struct ZlangObject *QueryObjectInLocalObjectsStack( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	int				local_objs_stack_info_curridx = GetCurrentLocalObjectsStackInfoIndex( rt ) ;
	struct ZlangObject		*obj = NULL ;
	int				stack_no ;
	
	if( obj_name == NULL || obj_name[0] == '\0' )
		return NULL;
	
_GOTO_RETRY_QUERY :
	for( stack_no = local_objs_stack_info->stack_local_var_top-1 ; stack_no >= local_objs_stack_info->stack_bottom ; stack_no-- )
	{
		obj = rt->local_objs_stack.objs_stack + stack_no ;
		if( obj->obj_name && obj->obj_name[0] && STRCMP( obj->obj_name , == , obj_name ) )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "QueryObjectInLocalObjectsStack[%s] return obj[%p]" , obj_name , obj )
			return obj;
		}
	}
	
	if( local_objs_stack_info->full_func_name == NULL && local_objs_stack_info_curridx > 0 )
	{
		local_objs_stack_info = GetPreviousObjectsStackInfo( rt , local_objs_stack_info ) ;
		if( local_objs_stack_info )
		{
			local_objs_stack_info_curridx--;
			goto _GOTO_RETRY_QUERY;
		}
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "QueryObjectInLocalObjectsStack[%s] return obj[%p]" , obj_name , NULL )
	return NULL;
}

struct ZlangObject *QueryObjectInLowerLocalObjectsStack( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	int				local_objs_stack_info_curridx = GetCurrentLocalObjectsStackInfoIndex( rt ) ;
	struct ZlangObject		*obj = NULL ;
	int				stack_no ;
	
	if( obj_name == NULL || obj_name[0] == '\0' )
		return NULL;
	
	local_objs_stack_info = GetPreviousObjectsStackInfo( rt , local_objs_stack_info ) ;
	if( local_objs_stack_info == NULL )
		return NULL;
	local_objs_stack_info_curridx--;
	
_GOTO_RETRY_QUERY :
	for( stack_no = local_objs_stack_info->stack_local_var_top-1 ; stack_no >= local_objs_stack_info->stack_bottom ; stack_no-- )
	{
		obj = rt->local_objs_stack.objs_stack + stack_no ;
		if( obj->obj_name && obj->obj_name[0] && STRCMP( obj->obj_name , == , obj_name ) )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "QueryObjectInLocalObjectsStack[%s] return obj[%p]" , obj_name , obj )
			return obj;
		}
	}
	
	if( local_objs_stack_info->full_func_name == NULL && local_objs_stack_info_curridx > 0 )
	{
		local_objs_stack_info = GetPreviousObjectsStackInfo( rt , local_objs_stack_info ) ;
		if( local_objs_stack_info )
		{
			local_objs_stack_info_curridx--;
			goto _GOTO_RETRY_QUERY;
		}
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "QueryObjectInLocalObjectsStack[%s] return obj[%p]" , obj_name , NULL )
	return NULL;
}

int GetLocalObjectCountInStackInfo( struct ZlangRuntime *rt , struct ZlangObjectsStackInfo *local_objs_stack_info )
{
	return local_objs_stack_info->stack_local_var_top-local_objs_stack_info->stack_out_params_top;
}

struct ZlangObject *GetLocalObjectInStackInfo( struct ZlangRuntime *rt , struct ZlangObjectsStackInfo *local_objs_stack_info , int local_obj_no )
{
	return rt->local_objs_stack.objs_stack+local_objs_stack_info->stack_out_params_top+(local_obj_no-1);
}

int GetOutputParameterCountInStackInfo( struct ZlangRuntime *rt , struct ZlangObjectsStackInfo *local_objs_stack_info )
{
	return local_objs_stack_info->stack_out_params_top-local_objs_stack_info->stack_in_params_top;
}

struct ZlangObject *GetOutputParameterInStackInfo( struct ZlangRuntime *rt , struct ZlangObjectsStackInfo *local_objs_stack_info , int out_param_no )
{
	return rt->local_objs_stack.objs_stack+local_objs_stack_info->stack_in_params_top+out_param_no-1;
}

int GetInputParameterCountInStackInfo( struct ZlangRuntime *rt , struct ZlangObjectsStackInfo *local_objs_stack_info )
{
	return local_objs_stack_info->stack_in_params_top-local_objs_stack_info->stack_bottom;
}

struct ZlangObject *GetInputParameterInStackInfo( struct ZlangRuntime *rt , struct ZlangObjectsStackInfo *local_objs_stack_info , int in_param_no )
{
	return rt->local_objs_stack.objs_stack+local_objs_stack_info->stack_bottom+(in_param_no-1);
}

int GetLocalObjectCountInLocalObjectStack( struct ZlangRuntime *rt )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	
	return GetLocalObjectCountInStackInfo(rt,local_objs_stack_info);
}

struct ZlangObject *GetLocalObjectInLocalObjectStack( struct ZlangRuntime *rt , int local_obj_no )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	
	return GetLocalObjectInStackInfo(rt,local_objs_stack_info,local_obj_no);
}

int GetOutputParameterCountInLocalObjectStack( struct ZlangRuntime *rt )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetFunctionLocalObjectsStackInfo( rt ) ;
	
	return GetOutputParameterCountInStackInfo(rt,local_objs_stack_info);
}

struct ZlangObject *GetOutputParameterInLocalObjectStack( struct ZlangRuntime *rt , int out_param_no )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetFunctionLocalObjectsStackInfo( rt ) ;
	
	if( out_param_no < 1 || out_param_no > local_objs_stack_info->stack_out_params_top-local_objs_stack_info->stack_in_params_top )
		return NULL;
	
	return GetOutputParameterInStackInfo(rt,local_objs_stack_info,out_param_no);
}

int GetInputParameterCountInLocalObjectStack( struct ZlangRuntime *rt )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetFunctionLocalObjectsStackInfo( rt ) ;
	
	return GetInputParameterCountInStackInfo(rt,local_objs_stack_info);
}

struct ZlangObject *GetInputParameterInLocalObjectStack( struct ZlangRuntime *rt , int in_param_no )
{
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetFunctionLocalObjectsStackInfo( rt ) ;
	
	if( in_param_no < 1 || in_param_no > local_objs_stack_info->stack_in_params_top-local_objs_stack_info->stack_bottom )
		return NULL;
	
	return GetInputParameterInStackInfo(rt,local_objs_stack_info,in_param_no);
}

void DebugLocalObjectsStack( struct ZlangRuntime *rt )
{
	int				local_objs_stack_info_curridx = GetCurrentLocalObjectsStackInfoIndex( rt ) ;
	struct ZlangObjectsStackInfo	*local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	int				stack_no ;
	struct ZlangObject		*obj = NULL ;
	
_GOTO_RETRY_DEBUG_OUTPUT :
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "LOCAL-OBJECTS-STACK - local_objs_stack_info[%d][%s]-[%d][%d][%d][%d]" , local_objs_stack_info_curridx,local_objs_stack_info->full_func_name , local_objs_stack_info->stack_bottom,local_objs_stack_info->stack_in_params_top,local_objs_stack_info->stack_out_params_top,local_objs_stack_info->stack_local_var_top );
	
	for( stack_no = local_objs_stack_info->stack_local_var_top-1 ; stack_no >= local_objs_stack_info->stack_out_params_top ; stack_no-- )
	{
		obj = rt->local_objs_stack.objs_stack + stack_no ;
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( TAB "local stack object - stack_no[%d] : local object : " , stack_no ); DebugPrintObject( rt , obj ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	}
	
	for( stack_no = local_objs_stack_info->stack_out_params_top-1 ; stack_no >= local_objs_stack_info->stack_in_params_top ; stack_no-- )
	{
		obj = rt->local_objs_stack.objs_stack + stack_no ;
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( TAB "local stack object - stack_no[%d] : out param : " , stack_no ); DebugPrintObject( rt , obj ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	}
	
	for( stack_no = local_objs_stack_info->stack_in_params_top-1 ; stack_no >= local_objs_stack_info->stack_bottom ; stack_no-- )
	{
		obj = rt->local_objs_stack.objs_stack + stack_no ;
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( TAB "local stack object - stack_no[%d] : in param : " , stack_no ); DebugPrintObject( rt , obj ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	}
	
	if( local_objs_stack_info->full_func_name == NULL && local_objs_stack_info_curridx > 0 )
	{
		local_objs_stack_info = GetPreviousObjectsStackInfo( rt , local_objs_stack_info ) ;
		if( local_objs_stack_info )
		{
			local_objs_stack_info_curridx--;
			goto _GOTO_RETRY_DEBUG_OUTPUT;
		}
	}
	
	return;
}

struct ZlangObject *CloneObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name , struct ZlangObject *clone_obj )
{
	struct ZlangObjectsStackInfo	*tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
	struct ZlangObject		*obj = NULL ;
	int				nret = 0 ;
	
	obj = PushLocalObjectsStack( rt , & (rt->tmp_objs_stack) , tmp_objs_stack_info ) ;
	if( obj == NULL )
		return NULL;
	
	nret = CloneObject( rt , & obj , obj_name , clone_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneZObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetZObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneStringObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetStringObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneBoolObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetBoolObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneShortObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetShortObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneUShortObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetUShortObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneIntObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetIntObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneUIntObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetUIntObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneLongObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetLongObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneULongObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetULongObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneFloatObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetFloatObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneDoubleObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetDoubleObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneArrayObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetArrayObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneListObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetListObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneListNodeObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetListNodeObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneMapObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetMapObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneIteratorObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetIteratorObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *CloneFunctionPtrObjectInTmpStack( struct ZlangRuntime *rt , char *obj_name )
{
	return CloneObjectInTmpStack( rt , obj_name , GetFunctionPtrObjectInRuntimeObjectsHeap(rt) );
}

struct ZlangObject *ReferObjectInTmpStack( struct ZlangRuntime *rt , struct ZlangObject *refer_obj )
{
	struct ZlangObjectsStackInfo	*tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
	struct ZlangObject		*obj = NULL ;
	int				nret = 0 ;
	
	obj = PushLocalObjectsStack( rt , & (rt->tmp_objs_stack) , tmp_objs_stack_info ) ;
	if( obj == NULL )
		return NULL;
	
	nret = ReferObject( rt , obj , refer_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

int InitTmpObjecsStackInfoArray( struct ZlangRuntime *rt )
{
	rt->tmp_objs_stack_info_array_allocount = ZLANG_TMP_OBJECTS_STACK_INFO_ARRAY_COUNT_DEFAULT ;
	rt->tmp_objs_stack_info_array = (struct ZlangObjectsStackInfo *)ZLMALLOC( sizeof(struct ZlangObjectsStackInfo) * rt->tmp_objs_stack_info_array_allocount ) ;
	if( rt->tmp_objs_stack_info_array == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for tmp_objs_stack_info_array" )
		return ZLANG_ERROR_ALLOC;
	}
	memset( rt->tmp_objs_stack_info_array , 0x00 , sizeof(struct ZlangObjectsStackInfo) * rt->tmp_objs_stack_info_array_allocount );
	
	return 0;
}

void CleanTmpObjecsStackInfoArray( struct ZlangRuntime *rt )
{
	ZLFREE( rt->tmp_objs_stack_info_array );
	
	return;
}

static int TryIncreaseTmpObjecsStackInfoArray( struct ZlangRuntime *rt )
{
	if( rt->tmp_objs_stack_info_array_curridx >= rt->tmp_objs_stack_info_array_allocount-1 )
	{
		int				new_objs_stack_info_array_allocount ;
		struct ZlangObjectsStackInfo	*new_objs_stack_info_array = NULL ;
		
		new_objs_stack_info_array_allocount = rt->tmp_objs_stack_info_array_allocount + ZLANG_TMP_OBJECTS_STACK_INFO_ARRAY_INCREASE_COUNT ;
		new_objs_stack_info_array = (struct ZlangObjectsStackInfo *)ZLREALLOC( rt->tmp_objs_stack_info_array , sizeof(struct ZlangObjectsStackInfo) * new_objs_stack_info_array_allocount ) ;
		if( new_objs_stack_info_array == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "ZLREALLOC memory for tmp_objs_stack_info_array" )
			return ZLANG_ERROR_ALLOC;
		}
		rt->tmp_objs_stack_info_array = new_objs_stack_info_array ;
		rt->tmp_objs_stack_info_array_allocount = new_objs_stack_info_array_allocount ;
	}
	
	return 0;
}

struct ZlangObjectsStackInfo *IncreaseTmpObjectsStackInfo( struct ZlangRuntime *rt , char *full_func_name )
{
	struct ZlangObjectsStackInfo	*old_tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
	int				stack_local_var_top ;
	struct ZlangObjectsStackInfo	*new_tmp_objs_stack_info = NULL ;
	int				nret = 0 ;
	
	stack_local_var_top = GetStackTop( rt , old_tmp_objs_stack_info );
	
	nret = TryIncreaseTmpObjecsStackInfoArray( rt ) ;
	if( nret )
		return NULL;
	
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangObjectsStackInfo *tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "before increase tmp stack : [%d][%s]-[%d][%d][%d][%d]" , rt->tmp_objs_stack_info_array_curridx,tmp_objs_stack_info->full_func_name , tmp_objs_stack_info->stack_bottom,tmp_objs_stack_info->stack_in_params_top,tmp_objs_stack_info->stack_out_params_top,tmp_objs_stack_info->stack_local_var_top )
	}
	
	rt->tmp_objs_stack_info_array_curridx++;
	new_tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
	new_tmp_objs_stack_info->stack_local_var_top = stack_local_var_top ;
	new_tmp_objs_stack_info->stack_out_params_top = stack_local_var_top ;
	new_tmp_objs_stack_info->stack_in_params_top = stack_local_var_top ;
	new_tmp_objs_stack_info->stack_bottom = stack_local_var_top ;
	new_tmp_objs_stack_info->full_func_name = full_func_name ;
	
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangObjectsStackInfo *tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "after increase tmp stack : [%d][%s]-[%d][%d][%d][%d]" , rt->tmp_objs_stack_info_array_curridx,tmp_objs_stack_info->full_func_name , tmp_objs_stack_info->stack_bottom,tmp_objs_stack_info->stack_in_params_top,tmp_objs_stack_info->stack_out_params_top,tmp_objs_stack_info->stack_local_var_top )
	}
	
	return new_tmp_objs_stack_info;
}

struct ZlangObjectsStackInfo *DecreaseTmpObjectsStackInfo( struct ZlangRuntime *rt )
{
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangObjectsStackInfo *tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "before decrease tmp stack : [%d][%s]-[%d][%d][%d][%d]" , rt->tmp_objs_stack_info_array_curridx,tmp_objs_stack_info->full_func_name , tmp_objs_stack_info->stack_bottom,tmp_objs_stack_info->stack_in_params_top,tmp_objs_stack_info->stack_out_params_top,tmp_objs_stack_info->stack_local_var_top )
	}
	
	PopupTmpObjectsStack( rt );
	
	memset( rt->tmp_objs_stack_info_array+rt->tmp_objs_stack_info_array_curridx , 0x00 , sizeof(struct ZlangObjectsStackInfo) );
	rt->tmp_objs_stack_info_array_curridx--;
	
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangObjectsStackInfo *tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "after decrease tmp stack : [%d][%s]-[%d][%d][%d][%d]" , rt->tmp_objs_stack_info_array_curridx,tmp_objs_stack_info->full_func_name , tmp_objs_stack_info->stack_bottom,tmp_objs_stack_info->stack_in_params_top,tmp_objs_stack_info->stack_out_params_top,tmp_objs_stack_info->stack_local_var_top )
	}
	
	return GetCurrentTmpObjectsStackInfo( rt );
}

struct ZlangObjectsStackInfo *GetCurrentTmpObjectsStackInfo( struct ZlangRuntime *rt )
{
	return rt->tmp_objs_stack_info_array+rt->tmp_objs_stack_info_array_curridx;
}

int PopupTmpObjectsStack( struct ZlangRuntime *rt )
{
	struct ZlangObjectsStackInfo	*tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
	int				nret = 0 ;
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "  PopupObjectsStack tmp_objs_stack_info[%s]-[%d][%d][%d][%d]" , tmp_objs_stack_info->full_func_name , tmp_objs_stack_info->stack_bottom,tmp_objs_stack_info->stack_in_params_top,tmp_objs_stack_info->stack_out_params_top,tmp_objs_stack_info->stack_local_var_top )
	
	while( tmp_objs_stack_info->stack_local_var_top > tmp_objs_stack_info->stack_bottom )
	{
		nret = PopupObjectsStack( rt , & (rt->tmp_objs_stack) , tmp_objs_stack_info ) ;
		if( nret )
			return nret;
	}
	
	tmp_objs_stack_info->stack_local_var_top = tmp_objs_stack_info->stack_bottom ;
	tmp_objs_stack_info->stack_out_params_top = tmp_objs_stack_info->stack_bottom ;
	tmp_objs_stack_info->stack_in_params_top = tmp_objs_stack_info->stack_bottom ;
	
	return 0;
}

void DebugTmpObjectsStack( struct ZlangRuntime *rt )
{
	int				tmp_objs_stack_info_curridx = GetCurrentTmpObjectsStackInfoIndex( rt ) ;
	struct ZlangObjectsStackInfo	*tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
	int				stack_no ;
	struct ZlangObject		*obj = NULL ;
	
_GOTO_RETRY_DEBUG_OUTPUT :
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TMP-OBJECTS-STACK - tmp_objs_stack_info[%d][%s]-[%d][%d][%d][%d]" , tmp_objs_stack_info_curridx,tmp_objs_stack_info->full_func_name , tmp_objs_stack_info->stack_bottom,tmp_objs_stack_info->stack_in_params_top,tmp_objs_stack_info->stack_out_params_top,tmp_objs_stack_info->stack_local_var_top );
	
	for( stack_no = tmp_objs_stack_info->stack_local_var_top-1 ; stack_no >= tmp_objs_stack_info->stack_bottom ; stack_no-- )
	{
		obj = rt->tmp_objs_stack.objs_stack + stack_no ;
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( TAB "tmp stack object - stack_no[%d] : tmp object : " , stack_no ); DebugPrintObject( rt , obj ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	}
	
	if( tmp_objs_stack_info->full_func_name == NULL && tmp_objs_stack_info_curridx > 0 )
	{
		tmp_objs_stack_info = GetPreviousObjectsStackInfo( rt , tmp_objs_stack_info ) ;
		if( tmp_objs_stack_info )
		{
			tmp_objs_stack_info_curridx--;
			goto _GOTO_RETRY_DEBUG_OUTPUT;
		}
	}
	
	return;
}

int GetCurrentTmpObjectsStackInfoIndex( struct ZlangRuntime *rt )
{
	return rt->tmp_objs_stack_info_array_curridx;
}

int InitDefersStack( struct ZlangRuntime *rt , struct ZlangDefersStack *defers_stack , int default_size , int increase_size )
{
	defers_stack->defers_stack_size = default_size ;
	defers_stack->defers_stack = (struct ZlangDefer *)ZLMALLOC( sizeof(struct ZlangDefer) * defers_stack->defers_stack_size ) ;
	if( defers_stack->defers_stack == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for defers_stack" )
		return ZLANG_ERROR_ALLOC;
	}
	memset( defers_stack->defers_stack , 0x00 , sizeof(struct ZlangDefer) * defers_stack->defers_stack_size );
	defers_stack->increase_size = increase_size ;
	
	return 0;
}

void CleanDefersStack( struct ZlangRuntime *rt , struct ZlangDefersStack *defers_stack )
{
	ZLFREE( defers_stack->defers_stack );
	
	return;
}

static int TryIncreaseDefersStack( struct ZlangRuntime *rt , struct ZlangDefersStack *defers_stack , struct ZlangDefersStackInfo *defers_stack_info )
{
	if( defers_stack_info->stack_top >= defers_stack->defers_stack_size )
	{
		int			new_defers_stack_size ;
		struct ZlangDefer	*new_defers_stack = NULL ;
		
		new_defers_stack_size = defers_stack->defers_stack_size + defers_stack->increase_size ;
		new_defers_stack = (struct ZlangDefer *)ZLREALLOC( defers_stack->defers_stack , sizeof(struct ZlangDefer) * new_defers_stack_size ) ;
		if( new_defers_stack == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "ZLREALLOC memory for defers_stack" )
			return ZLANG_ERROR_ALLOC;
		}
		defers_stack->defers_stack = new_defers_stack ;
		defers_stack->defers_stack_size = new_defers_stack_size ;
	}
	
	return 0;
}

struct ZlangDefer *PushLocalDefersStack( struct ZlangRuntime *rt , struct ZlangDefersStack *defers_stack , struct ZlangDefersStackInfo *defers_stack_info )
{
	struct ZlangDefer		*defer = NULL ;
	int				nret = 0 ;
	
	nret = TryIncreaseDefersStack( rt , defers_stack , defers_stack_info ) ;
	if( nret )
		return NULL;
	
	defer = defers_stack->defers_stack + defers_stack_info->stack_top ;
	memset( defer , 0x00 , sizeof(struct ZlangDefer) );
	defers_stack_info->stack_top++;
	
	return defer;
}

int PopupDeferStack( struct ZlangRuntime *rt , struct ZlangDefersStack *defers_stack , struct ZlangDefersStackInfo *defers_stack_info )
{
	int				stack_no ;
	struct ZlangDefer		*defer = NULL ;
	struct ZlangTokenDataUnitHeader	*token_info = NULL ;
	char				*token = NULL ;
	int				nret = 0 ;
	
	if( defers_stack_info->stack_top <= 0 )
		return ZLANG_ERROR_PARAMETER;
	
	stack_no = defers_stack_info->stack_top-1 ;
	defer = defers_stack->defers_stack + stack_no ;
	token_info = (struct ZlangTokenDataUnitHeader *)GetAppendonlyDataUnitUserHeader(defer->defer_begin_token_dataunit) ;
	token = (char*)token_info + sizeof(struct ZlangTokenDataUnitHeader) ;
	TOKENTYPE_TO_STRING( token_info->token_type , _zlang_token_type_str )
	TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "    popup defer from defer_stack_no[%d] begin[%s][%"PRIi32"][%"PRIi32"]-[%s][%"PRIi32"]-[%p][%p][%d]-[%.*s]" , stack_no , token_info->source_filename,token_info->source_row,token_info->source_col , _zlang_token_type_str,token_info->token_len , token_info->p1,token_info->p2,token_info->n3 , token_info->token_len,token ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	
	rt->travel_token_datapage_header = defer->defer_begin_token_datapage_header ;
	rt->travel_token_dataunit = defer->defer_begin_token_dataunit ;
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CALL InterpretStatement" )
	nret = InterpretStatement( rt ) ;
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterpretStatement return[%d]" , nret )
	if( nret != ZLANG_INFO_END_OF_STATEMENT )
	{
		return nret;
	}
	
	defers_stack_info->stack_top--;
	
	return 0;
}

int PopupDefersStack( struct ZlangRuntime *rt )
{
	struct ZlangDefersStackInfo	*defers_stack_info = GetCurrentDefersStackInfo( rt ) ;
	int				nret = 0 ;
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "  PopupDefersStack defers_stack_info[%s]-[%d][%d]" , defers_stack_info->full_func_name , defers_stack_info->stack_bottom,defers_stack_info->stack_top )
	
	while( defers_stack_info->stack_top > defers_stack_info->stack_bottom )
	{
		nret = PopupDeferStack( rt , & (rt->defers_stack) , defers_stack_info ) ;
		if( nret )
			return nret;
	}
	
	defers_stack_info->stack_top = defers_stack_info->stack_bottom ;
	
	return 0;
}

int InitDefersStackInfoArray( struct ZlangRuntime *rt )
{
	rt->defers_stack_info_array_allocount = ZLANG_DEFERS_STACK_INFO_ARRAY_COUNT_DEFAULT ;
	rt->defers_stack_info_array = (struct ZlangDefersStackInfo *)ZLMALLOC( sizeof(struct ZlangDefersStackInfo) * rt->defers_stack_info_array_allocount ) ;
	if( rt->defers_stack_info_array == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for defers_stack_info_array" )
		return ZLANG_ERROR_ALLOC;
	}
	memset( rt->defers_stack_info_array , 0x00 , sizeof(struct ZlangDefersStackInfo) * rt->defers_stack_info_array_allocount );
	
	return 0;
}

void CleanDefersStackInfoArray( struct ZlangRuntime *rt )
{
	ZLFREE( rt->defers_stack_info_array );
	
	return;
}

static int TryIncreaseDeferStackInfoArray( struct ZlangRuntime *rt )
{
	if( rt->defers_stack_info_array_curridx >= rt->defers_stack_info_array_allocount-1 )
	{
		int				new_defers_stack_info_array_allocount ;
		struct ZlangDefersStackInfo	*new_defers_stack_info_array = NULL ;
		
		new_defers_stack_info_array_allocount = rt->defers_stack_info_array_allocount + ZLANG_DEFERS_STACK_INFO_ARRAY_INCREASE_COUNT ;
		new_defers_stack_info_array = (struct ZlangDefersStackInfo *)ZLREALLOC( rt->defers_stack_info_array , sizeof(struct ZlangDefersStackInfo) * new_defers_stack_info_array_allocount ) ;
		if( new_defers_stack_info_array == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "ZLREALLOC memory for defers_stack_info_array" )
			return ZLANG_ERROR_ALLOC;
		}
		rt->defers_stack_info_array = new_defers_stack_info_array ;
		rt->defers_stack_info_array_allocount = new_defers_stack_info_array_allocount ;
	}
	
	return 0;
}

struct ZlangDefersStackInfo *IncreaseDefersStackInfo( struct ZlangRuntime *rt , char *full_func_name )
{
	struct ZlangDefersStackInfo	*old_defers_stack_info = GetCurrentDefersStackInfo( rt ) ;
	int				stack_top ;
	struct ZlangDefersStackInfo	*new_defers_stack_info = NULL ;
	int				nret = 0 ;
	
	stack_top = old_defers_stack_info->stack_top ;
	
	nret = TryIncreaseDeferStackInfoArray( rt ) ;
	if( nret )
		return NULL;
	
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangDefersStackInfo *defers_stack_info = GetCurrentDefersStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "before increase defers stack : [%d][%s]-[%d][%d]" , rt->defers_stack_info_array_curridx,defers_stack_info->full_func_name , defers_stack_info->stack_bottom,defers_stack_info->stack_top )
	}
	
	rt->defers_stack_info_array_curridx++;
	new_defers_stack_info = GetCurrentDefersStackInfo( rt ) ;
	new_defers_stack_info->stack_top = stack_top ;
	new_defers_stack_info->stack_bottom = stack_top ;
	new_defers_stack_info->full_func_name = full_func_name ;
	
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangDefersStackInfo *defers_stack_info = GetCurrentDefersStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "after increase defers stack : [%d][%s]-[%d][%d]" , rt->defers_stack_info_array_curridx,defers_stack_info->full_func_name , defers_stack_info->stack_bottom,defers_stack_info->stack_top )
	}
	
	return new_defers_stack_info;
}

struct ZlangDefersStackInfo *DecreaseDefersStackInfo( struct ZlangRuntime *rt )
{
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangDefersStackInfo *defers_stack_info = GetCurrentDefersStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "before decrease defers stack : [%d][%s]-[%d][%d]" , rt->defers_stack_info_array_curridx,defers_stack_info->full_func_name , defers_stack_info->stack_bottom,defers_stack_info->stack_top )
	}
	
	PopupDefersStack( rt );
	
	memset( rt->defers_stack_info_array+rt->defers_stack_info_array_curridx , 0x00 , sizeof(struct ZlangDefersStackInfo) );
	rt->defers_stack_info_array_curridx--;
	
	TEST_RUNTIME_DEBUG( rt )
	{
		struct ZlangDefersStackInfo *defers_stack_info = GetCurrentDefersStackInfo( rt ) ;
		PRINT_TABS_AND_FORMAT( rt , "after decrease defers stack : [%d][%s]-[%d][%d]" , rt->defers_stack_info_array_curridx,defers_stack_info->full_func_name , defers_stack_info->stack_bottom,defers_stack_info->stack_top )
	}
	
	return GetCurrentDefersStackInfo( rt );
}

void SetDefersStackFullFuncName( struct ZlangDefersStackInfo *defers_stack_info , char *full_func_name )
{
	defers_stack_info->full_func_name = full_func_name ;
	
	return;
}

struct ZlangDefersStackInfo *GetCurrentDefersStackInfo( struct ZlangRuntime *rt )
{
	return rt->defers_stack_info_array+rt->defers_stack_info_array_curridx;
}

int GetCurrentDefersStackInfoIndex( struct ZlangRuntime *rt )
{
	return rt->defers_stack_info_array_curridx;
}

struct ZlangDefersStackInfo *GetPreviousDefersStackInfo( struct ZlangRuntime *rt , struct ZlangDefersStackInfo *defers_stack_info )
{
	if( defers_stack_info == rt->defers_stack_info_array )
		return NULL;
	
	return defers_stack_info-1;
}

void DebugDefersStack( struct ZlangRuntime *rt )
{
	int				defers_stack_info_curridx = GetCurrentDefersStackInfoIndex( rt ) ;
	struct ZlangDefersStackInfo	*defers_stack_info = GetCurrentDefersStackInfo( rt ) ;
	int				stack_no ;
	struct ZlangDefer		*defer = NULL ;
	struct ZlangTokenDataUnitHeader	*token_info = NULL ;
	char				*token = NULL ;
	
_GOTO_RETRY_DEBUG_OUTPUT :
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "DEFER-STACK - defers_stack_info[%d][%s]-[%d][%d]" , defers_stack_info_curridx,defers_stack_info->full_func_name , defers_stack_info->stack_bottom,defers_stack_info->stack_top );
	
	for( stack_no = defers_stack_info->stack_top-1 ; stack_no >= defers_stack_info->stack_bottom ; stack_no-- )
	{
		defer = rt->defers_stack.defers_stack + stack_no ;
		token_info = (struct ZlangTokenDataUnitHeader *)GetAppendonlyDataUnitUserHeader(defer->defer_begin_token_dataunit) ;
		token = (char*)token_info + sizeof(struct ZlangTokenDataUnitHeader) ;
		TOKENTYPE_TO_STRING( token_info->token_type , _zlang_token_type_str )
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( TAB "defer stack defer - stack_no[%d] begin[%s][%"PRIi32"][%"PRIi32"]-[%s][%"PRIi32"]-[%p][%p][%d]-[%.*s]" , stack_no , token_info->source_filename,token_info->source_row,token_info->source_col , _zlang_token_type_str,token_info->token_len , token_info->p1,token_info->p2,token_info->n3 , token_info->token_len,token ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	}
	
	if( defers_stack_info->full_func_name == NULL && defers_stack_info_curridx > 0 )
	{
		defers_stack_info = GetPreviousDefersStackInfo( rt , defers_stack_info ) ;
		if( defers_stack_info )
		{
			defers_stack_info_curridx--;
			goto _GOTO_RETRY_DEBUG_OUTPUT;
		}
	}
	
	return;
}

int IncreaseStackInfo( struct ZlangRuntime *rt , char *full_func_name )
{
	struct ZlangObjectsStackInfo	*new_local_objs_stack_info = NULL ;
	struct ZlangObjectsStackInfo	*new_tmp_objs_stack_info = NULL ;
	struct ZlangDefersStackInfo	*new_defers_stack_info = NULL ;
	
	new_local_objs_stack_info = IncreaseLocalObjectsStackInfo( rt , full_func_name ) ;
	if( new_local_objs_stack_info == NULL )
		return GetRuntimeErrorNo(rt);
	
	new_tmp_objs_stack_info = IncreaseTmpObjectsStackInfo( rt , full_func_name ) ;
	if( new_tmp_objs_stack_info == NULL )
		return GetRuntimeErrorNo(rt);
	
	new_defers_stack_info = IncreaseDefersStackInfo( rt , full_func_name ) ;
	if( new_defers_stack_info == NULL )
		return GetRuntimeErrorNo(rt);
	
	return 0;
}

int DecreaseStackInfo( struct ZlangRuntime *rt )
{
	struct ZlangObjectsStackInfo	*old_local_objs_stack_info = NULL ;
	struct ZlangObjectsStackInfo	*old_tmp_objs_stack_info = NULL ;
	struct ZlangDefersStackInfo	*old_defers_stack_info = NULL ;
	
	old_defers_stack_info = DecreaseDefersStackInfo( rt ) ;
	if( old_defers_stack_info == NULL )
		return GetRuntimeErrorNo(rt);
	
	old_local_objs_stack_info = DecreaseLocalObjectsStackInfo( rt ) ;
	if( old_local_objs_stack_info == NULL )
		return GetRuntimeErrorNo(rt);
	
	old_tmp_objs_stack_info = DecreaseTmpObjectsStackInfo( rt ) ;
	if( old_tmp_objs_stack_info == NULL )
		return GetRuntimeErrorNo(rt);
	
	return 0;
}

void SetStackTopFullFuncName( struct ZlangRuntime *rt , char *full_func_name )
{
	struct ZlangObjectsStackInfo		*local_objs_stack_info = NULL ;
	struct ZlangObjectsStackInfo		*tmp_objs_stack_info = NULL ;
	struct ZlangDefersStackInfo		*defers_stack_info = NULL ;
	
	local_objs_stack_info = GetCurrentLocalObjectsStackInfo( rt ) ;
	tmp_objs_stack_info = GetCurrentTmpObjectsStackInfo( rt ) ;
	defers_stack_info = GetCurrentDefersStackInfo( rt ) ;
	
	SetObjectsStackFullFuncName( local_objs_stack_info , full_func_name );
	SetObjectsStackFullFuncName( tmp_objs_stack_info , full_func_name );
	SetDefersStackFullFuncName( defers_stack_info , full_func_name );
	
	return;
}

void DebugStack( struct ZlangRuntime *rt )
{
	DebugLocalObjectsStack( rt );
	DebugTmpObjectsStack( rt );
	DebugDefersStack( rt );
	
	return;
}

